<?php

namespace App\Jobs;

use App\Models\ExportLog;
use function foo\func;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Support\Facades\Storage;
use SuperClosure\Serializer;

class ExportData implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, SerializesModels;

    public $queue = 'export';

    public $tries = 2;

    protected $header;

    protected $query;

    protected $call;

    protected $filename;

    protected $data; //传入数据 没有则执行查询

    protected $serialize;

    /**
     * Create a new job instance.
     *
     * @return void
     */
    public function __construct($header,$query,$call,$filename,$data = false)
    {
        $this->header = $header;
        $this->query = $query;
        $this->call = $call;
        $this->filename = $filename;
        $this->data = $data;

        $this->serialize = new Serializer();
        $this->setLog(ExportLog::StatusWait);

    }

    protected function setLog($status = 0,$completed_at = false){
        $exportLog = ExportLog::firstOrNew(['filename' => $this->filename]);
        $exportLog->status = $status;
        if($completed_at){
            $exportLog->completed_at = time();
        }
        $exportLog->save();
    }

    protected function setQuery(){

        return $this->serialize->unserialize($this->query);

    }

    protected function setCall(){

        return $this->call ? $this->serialize->unserialize($this->call) : function($param){return $param;};

    }
    /**
     * Execute the job.
     *
     * @return void
     */
    public function handle()
    {
        /* 生成PATH路径 */
        $path = Storage::disk('exports')->path($this->filename);

        try{
            $fp = fopen($path, "a");  //a表示追加模式.
            fwrite($fp, chr(0xEF).chr(0xBB).chr(0xBF)); // 添加 BOM,不然excel打开csv是乱码
            fputcsv($fp,$this->header);

            if($this->data === false){

                $query = $this->setQuery();//获取数据查询函数
                $call = $this->setCall();//获取数据处理函数

                $response = $query()->chunk(1000,function($datas) use ($fp,$call){
                    foreach($datas as $data){

                        $data = $call($data);

                        fputcsv($fp, array_merge($this->header,json_decode(json_encode($data), true)));

                    }

                });
                if(!$response) throw new \Exception('失败');

            }else if(is_array($this->data)){

                foreach($this->data as $d){

                    $d = array_intersect_key($d,$this->header);

                    $result = array_replace($this->header,$d);

                    fputcsv($fp, json_decode(json_encode($result), true));
                }

            }

        }catch (\Exception $exception){
            unlink($path);
            $this->setLog(ExportLog::StatusFail);
            $this->fail();

        }

        $this->setLog(ExportLog::StatusSuccess,true);
        fclose($fp);
        $this->delete();

    }
}
